#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "package.h"
#include <QDebug>
#include <QTextStream>
#include <QPushButton>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QTextStream>
#include <QLabel>
#include <QWidget>
#include <QSpinBox>
#include <QLineEdit>
#include <QTextEdit>
#include <QMessageBox>
#include <QStackedWidget>
#include <QTableWidget>
#include <QHeaderView>
#include <QTimer>
#include <QPainter>
#include <QPointF>
#include <QMouseEvent>

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{

    ui->setupUi(this);

    setGeometry(380, 120, 800, 600);
    setFixedSize(800, 600);
    /********************分隔线********************/
    ui->stackedWidget->setCurrentIndex(0);  //初始化界面为界面0
    /* 时间模块 */
    timer->setTimerType(Qt::PreciseTimer);
    timer->start(1000 / pkg->myClock.fps);
    connect(timer, &QTimer::timeout ,[=]{
        pkg->myClock.setTime();
        QString timeStr = pkg->myClock.time.toString("hh:mm:ss");
        timeLbl->setText(timeStr);
        if(ui->stackedWidget->currentIndex() == 5)
        {
            Motion();
        }
    });
    /* 日志模块 */
    CheckLog();
    /* 界面零 */
    /* 作为启动界面，提供帮助文档和一些版本信息，用于时间校对 */

    //确认后，由第零界面跳转至第一界面
    connect(ui->btn_page0_check,&QPushButton::clicked,[=](){
        ui->stackedWidget->setCurrentIndex(1);
        pkg->myClock.setTime(QTime().currentTime().msecsTo(ui->ted_page0_timeEdit->time()));
        SendLog("设置时间为：" + pkg->myClock.time.toString("hh:mm:ss"));
    });
    //读取用户输入的时间数据
    connect(ui->btn_page0_assistDocumentation,&QPushButton::clicked,[=](){
        QFile assistFile(":/file/File/assistDocument.txt");
        if ( ! assistFile.open(QIODevice::ReadOnly))
            qDebug() << "打开帮助文档文件错误";
        QWidget *assistWindows = new QWidget();
        assistWindows->setAttribute(Qt::WA_DeleteOnClose);
        QTextEdit *assistText = new QTextEdit(assistWindows);
        assistText->setAttribute(Qt::WA_DeleteOnClose);
        assistWindows->setWindowTitle("帮助文档");
        assistText->setReadOnly(true);
        assistWindows->setFixedSize(600,600);
        assistText->setFixedSize(600,600);
        QByteArray array = assistFile.readAll();
        assistText->setText(array);
        assistWindows->show();
        assistFile.close();
    });
//  点击帮助文档按钮后，弹出相应的窗口，窗口会展示/document/File/assistDocument中的文本信息，关闭窗口后关闭文件
//    此处包含页面的初始设置（大小，只读，标题）

    connect(ui->btn_page0_clearLog, &QPushButton::clicked, [=](){
        QFile::remove(pkg->state.logPath);
        QFileInfo file(pkg->state.logPath);
        if( ! file.isFile())
            ui->statusbar->showMessage("日志文件已删除",1000);
        else
            ui->statusbar->showMessage("日志文件删除失败",1000);
        SendLog("已清除日志");
    });

    /*界面一*/
    /*用户的输入界面，用于确认导航所需的信息*/

    ui->cmbox_page1_strategy->addItem("距离最短");
    ui->cmbox_page1_strategy->addItem("耗时最少");
    ui->cmbox_page1_strategy->addItem("限定必经点");

    ui->cmbox_page1_vehicle->addItem("步行");
    ui->cmbox_page1_vehicle->addItem("骑行");

    connect(ui->btn_page1_search,&QPushButton::clicked,[=](){
        pkg->inP.startingPoint = ui->line_page1_startingPoint->text();
        if( ! pkg->inP.startingPoint.isEmpty())
        {
            ui->line_page2_location->setText(pkg->inP.startingPoint);        //初始化搜索框内容为用户输入的起点
            ui->list_page2_matchingLocations->clear();
            ui->list_page2_matchingLocations->addItems(Matching(ui->line_page2_location));
        }
        SendLog("输入起点为：" + pkg->inP.startingPoint);
        pkg->inP.terminalPoint = ui->line_page1_terminalPoint->text();   //用户点击搜索后，将起点和终点的输入结果保存
        SendLog("输入终点为：" + pkg->inP.terminalPoint);
        if(ui->cmbox_page1_strategy->currentIndex() == 2)           //策略
        {
            pkg->inP.strategy = 2;

            ui->btn_page3_confirm->setText("增加必经点");
        }
        else
        {
            if(ui->cmbox_page1_strategy->currentIndex() == 0)
                pkg->inP.strategy = 0;
            else
                pkg->inP.strategy = 1;
            ui->btn_page3_confirm->setText("开始导航");
        }
        SendLog("设置出行策略为：" + ui->cmbox_page1_strategy->currentText());
        pkg->inP.vehicle = ui->cmbox_page1_vehicle->currentIndex();
        SendLog("设置出行方式为：" + ui->cmbox_page1_vehicle->currentText());
        ui->stackedWidget->setCurrentIndex(2);
    });

    /*界面二*/
    /*模糊匹配界面，用于向用户确定起点*/
    connect(ui->btn_page2_back,&QPushButton::clicked,[=](){
        ui->line_page1_startingPoint->setText(pkg->inP.startingPoint);
        ui->line_page1_terminalPoint->setText(pkg->inP.terminalPoint);
        ui->stackedWidget->setCurrentIndex(1);
    });
    ConnectSearchBtn(ui->btn_page2_search, ui->list_page2_matchingLocations);
    ConnectConfirmBtn(ui->btn_page2_confirm);
    connect(ui->btn_page2_confirm,&QPushButton::clicked,[=](){
        if(pkg->state.allowPathFlag == 2)
        {
            pkg->state.allowPathFlag = 0;
            SendLog("设置校区为：" + StringCampus());
            SendLog("设置起点为：" + pkg->inP.startingPoint);
            if( ! pkg->inP.terminalPoint.isEmpty())
            {
                ui->line_page3_location->setText(pkg->inP.terminalPoint);       //初始化搜索框内容为用户输入的终点
                ui->list_page3_matchingLocations->clear();
                ui->list_page3_matchingLocations->addItems(Matching(ui->line_page3_location));
            }
            ui->btn_page3_back->setVisible(true);
            ui->stackedWidget->setCurrentIndex(3);
            ConnectConfirmBtn(ui->btn_page3_confirm);
            if(pkg->inP.strategy == 0 || pkg->inP.strategy == 1){
                connect(ui->btn_page3_confirm,&QPushButton::clicked,[=](){
                    if(pkg->state.allowPathFlag == 2)
                    {
                        pkg->state.allowPathFlag = 0;
                        SendLog("设置终点为：" + pkg->inP.terminalPoint);
                        guiderCampus();
                        SetPage5();
                    }
                });
            }    //假如用户不需要增加必经点，终点确认后即可开始导航
            else{
                connect(ui->btn_page3_confirm,&QPushButton::clicked,[=](){
                    if(pkg->state.allowPathFlag == 2)
                    {
                        pkg->state.allowPathFlag = 0;
                        SendLog("设置终点为：" + pkg->inP.terminalPoint);
                        pkg->inP.viaPoint << pkg->inP.startingPoint;
                        SetWaypointsTxt();
                        ui->line_page4_location->clear();                      //初始化搜索框内容为空
                        ui->list_page4_matchingLocations->clear();
                        ui->stackedWidget->setCurrentIndex(4);
                    }
                });
                }//假如用户需要增加必经点，则跳转至必经点的处理页面
            }
        });

    /*界面三*/
    /*模糊匹配界面，用于向用户确定终点*/
    ConnectBackBtn(ui->btn_page3_back);
    connect(ui->btn_page3_back,&QPushButton::clicked,[=](){
       ui->stackedWidget->setCurrentIndex(2);
       ui->btn_page3_confirm->disconnect();                   //connect中套connect时，返回要清除连接
   });
    ConnectSearchBtn(ui->btn_page3_search, ui->list_page3_matchingLocations);
    //界面开始导航/增加必经点功能在界面二中确定

    /* 界面四 */
    /* 模糊匹配界面，用于从用户处获取必经点 */
    ConnectBackBtn(ui->btn_page4_back);
    connect(ui->btn_page4_back,&QPushButton::clicked,[=](){
     pkg->inP.viaPoint.clear();
     ui->stackedWidget->setCurrentIndex(3);
 });
    //点击返回按钮后，清空链表数据并返回终点界面
    ConnectSearchBtn(ui->btn_page4_search, ui->list_page4_matchingLocations);
    ConnectConfirmBtn(ui->btn_page4_addWaypoint);
    connect(ui->btn_page4_addWaypoint,&QPushButton::clicked,[=](){
        if(pkg->state.allowPathFlag == 2)
        {
            pkg->state.allowPathFlag = 0;
            pkg->inP.viaPoint << ui->list_page4_matchingLocations->currentItem()->text().split("]").at(1);
            SetWaypointsTxt();
            ui->line_page4_location->clear();
            ui->list_page4_matchingLocations->clear();
            SendLog("设置必经点为：" + pkg->inP.viaPoint.last());
        }
    });     //点击增加必经点按钮，清空输入框，将数据传到链表
    ConnectConfirmBtn(ui->btn_page4_confirm);
    connect(ui->btn_page4_confirm,&QPushButton::clicked,[=](){
        if(pkg->state.allowPathFlag == 2)
        {
            pkg->inP.viaPoint << pkg->inP.terminalPoint;
            int viaPointNum = pkg->inP.viaPoint.size();
            for (int i = 0;i < (viaPointNum-1);i++)
            {
                pkg->inP.viaNum = i;
                guider->findNavigationRoute(pkg);
            }

            pkg->state.allowPathFlag = 0;
            SetPage5();
        }
    });     //点击开始导航按钮，将数据传到链表

    /*界面五*/
    /*地图界面，提供导航模拟*/

    ConnectBackBtn(ui->btn_page5_changeDestination);
    connect(ui->btn_page5_changeDestination,&QPushButton::clicked,[=](){
        setGeometry(380, 120, 800, 600);
        setFixedSize(800, 600);
        ui->btn_page3_back->setVisible(false);
        guider->AddCurrentPoint(pkg);
        pkg->state.currentLocationNum = 0;
        ui->line_page3_location->clear();
        ui->list_page3_matchingLocations->clear();
        if(pkg->inP.strategy == 2)
        {
            pkg->inP.viaPoint.clear();//重新规划路线时，暂定清空链表
            pkg->inP.viaPoint << pkg->inP.startingPoint;
        }
        pkg->myClock.speed=1;
        pkg->state.navigationRuningFlag = false;
        if(pkg->state.suspendFlag)
        {
            pkg->state.suspendFlag = 0;
            ui->btn_page5_suspend->setText("暂停");
            SendLog("暂停结束，更换目的地中");
        }
        ui->stackedWidget->setCurrentIndex(3);
    });
    connect(ui->btn_page5_suspend, &QPushButton::clicked, [=](){
        if(pkg->state.suspendFlag)
        {
            pkg->state.suspendFlag = 0;
            pkg->myClock.speed = pkg->myClock.userSpeed;
            ui->btn_page5_suspend->setText("暂停");
            SendLog("暂停结束");
        }
        else
        {
            pkg->state.suspendFlag = 1;
            pkg->myClock.speed=0;
            ui->btn_page5_suspend->setText("开始");
            SendLog("时间暂停");
        }
    });
    connect(ui->btn_page5_surroundings,&QPushButton::clicked ,[=]{
        guider->findMatchingLocation(pkg);
        connect(this, SIGNAL(SendPkg(package *)), surWidget, SLOT(GetPkg(package *)));
        emit SendPkg(pkg);
        disconnect(this, SIGNAL(SendPkg(package *)), surWidget, SLOT(GetPkg(package *)));
        surWidget->show();
    });
    //点击查看周边按钮后，弹出新页面，该页面含有一个QTableWidget型变量

    connect(surWidget, SIGNAL(SendSrdNum(int)), this, SLOT(GetSrdNum(int)));

    connect(ui->spx_page5_spinBox,&QSpinBox::textChanged,[=]{
        pkg->myClock.userSpeed = ui->spx_page5_spinBox->value();
        if(pkg->state.suspendFlag == 0)
            pkg->myClock.speed = pkg->myClock.userSpeed;
        SendLog("设置时间倍率为：" + QString::number(pkg->myClock.userSpeed));
    });

    /* 状态栏 */
    ui->statusbar->addWidget(addressLbl);
    ui->statusbar->addPermanentWidget(timeLbl);
//    设置状态栏左边信息为实时地址，右边信息为当前时间
}

MainWindow::~MainWindow()
{
    if(debug)
        qDebug() << "导航运行时长：" << clock() / 1000 / 60 << "min" <<
    (clock() / 1000.) - (clock() / 1000 / 60 * 60) << "s";
    delete pkg;
    delete guider;
    delete surWidget;
    delete initP;
    delete initA;
    delete ui;
}

/**
 * @brief 用于导航开始时记录日志，如果日志丢失则在日志中记录
 */
void MainWindow::CheckLog()
{
    if (QDir().exists(pkg->state.logPath2))
        pkg->state.logPath = pkg->state.logPath2;
    else
        pkg->state.logPath = pkg->state.logPath1;

    logFile.setFileName(pkg->state.logPath);

    if (QDir().exists(pkg->state.logPath))
    {
        SendLog("导航系统开始运行");
        if(debug)
            SendLog("debug运行中");
    }
    else
    {
        SendLog("导航系统开始运行");
        SendLog("日志文件丢失");
    }
}

/**
 * @brief 用于记录日志
 * @param str   日志所输出的字符串
 */
void MainWindow::SendLog(QString str)
{
    if( ! logFile.open(QIODevice::Append))
        qDebug() << "打开日志文件错误";
    QTextStream stream(&logFile);
    QString log = "<" + pkg->myClock.time.toString("hh:mm:ss")
    + ">" + str;
    stream << log << "\r\n";
    logFile.close();
}

/**
 * @brief 用于连接返回按钮执行某些重复性的操作：
 * 返回时将合法路径Flag置为1
 */
void MainWindow::ConnectBackBtn(QPushButton *btn)
{
    connect(btn, &QPushButton::clicked, [=](){
        pkg->state.allowPathFlag = 1;
    });
}

QString MainWindow::StringCampus()
{
    if(pkg->inP.campus)
        return "[沙河]";
    else
        return "[西土城]";
}

QString MainWindow::StringCampus(int campus)
{
    if(campus)
        return "[沙河]";
    else
        return "[西土城]";
}

/**
 * @brief 用于界面四中路线的显示
 */
void MainWindow::SetWaypointsTxt()
{
    QString str;
    str = StringCampus() + "(起点)" + pkg->inP.startingPoint + " -> ";
    for(int i = 1; i < pkg->inP.viaPoint.size(); i++)
    {
        str += pkg->inP.viaPoint[i] + " -> ";
    }
    str += "(终点)" + pkg->inP.terminalPoint;
    ui->txt_page4_route->setText(str);
}

bool MainWindow::KMP(QString ts, QString ps)
{
    QList<QString> t = ts.split("");
    t.removeFirst(); t.removeLast();
    QList<QString> p = ps.split("");
    p.removeFirst(); p.removeLast();
    int i = 0; // 主串的位置
    int j = 0; // 模式串的位置
    QList<int> next = GetNext(ps);
    while (i < t.size() && j < p.size())
    {
        if (j == -1 || t.at(i) == p.at(j))
        { // 当j为-1时，要移动的是i，当然j也要归0
            i++;
            j++;
        }
        else
        {
            j = next.at(j); // j回到指定位置
        }
    }

    if (j == p.size())
    {
        return true;
    }
    else
    {
        return false;
    }
}

QList<int> MainWindow::GetNext(QString ps)
{
    QList<QString> p = ps.split("");
    p.removeFirst(); p.removeLast();
    QList<int> next;
    next << -1;
    int j = 0;
    int k = -1;
    while (j < p.size() - 1)
    {
     if (k == -1 || p.at(j) == p.at(k))
     {
      if (p.at(++j) == p.at(++k))
          { // 当两个字符相等时要跳过
              next << next.at(k);
          }
          else
          {
              next << k;
          }
      }
      else
      {
         k = next.at(k);
     }
 }
 return next;
}

QList<QString> MainWindow::Matching(QLineEdit *line)
{
    QList<QString> temp;
    int start = pkg->inP.strategy == 2 ? pkg->inP.campus ? 1 : guider->map->pointBuildingNumXiTuCheng : 1;
    int max = pkg->inP.strategy == 2 ? pkg->inP.campus ? guider->map->pointBuildingNumXiTuCheng : guider->map->pointBuildingNum.size() : guider->map->pointBuildingNum.size();
    for(int i = start; i < max; i++)
    {
        for (int j = 0; j < guider->map->point[guider->map->pointBuildingNum.at(i)].pointName.size(); j++)
        {
            if(guider->map->point[guider->map->pointBuildingNum.at(i)].pointType && KMP(guider->map->point[guider->map->pointBuildingNum.at(i)].pointName.at(j), line->text()))
            {
                if( ! QString::compare(guider->map->point[guider->map->pointBuildingNum.at(i)].pointName.at(j), line->text()))
                {
                    temp.insert(0, StringCampus(guider->map->point[guider->map->pointBuildingNum.at(i)].pointCampus)
                            + guider->map->point[guider->map->pointBuildingNum.at(i)].pointName.at(j));
                }
                else
                {
                    temp << StringCampus(guider->map->point[guider->map->pointBuildingNum.at(i)].pointCampus)
                            + guider->map->point[guider->map->pointBuildingNum.at(i)].pointName.at(j);
                }
            }
        }
    }
    return temp;
}

/**
 * @brief 用于连接搜索按钮执行某些重复性的操作：
 * 点击列表中某项传入inP，并且设置输入框为该选项
 */
void MainWindow::ConnectSearchBtn(QPushButton *btn, QListWidget *list)
{
    connect(btn, &QPushButton::clicked, [=](){
        list->clear();

        switch (ui->stackedWidget->currentIndex())
        {
        case 2:
            ui->list_page2_matchingLocations->addItems(Matching(ui->line_page2_location));
            break;
        case 3:
            ui->list_page3_matchingLocations->addItems(Matching(ui->line_page3_location));
            break;
        case 4:
            ui->list_page4_matchingLocations->addItems(Matching(ui->line_page4_location));
            break;
        }
    });
    connect(list, &QListWidget::itemClicked, [=](QListWidgetItem * item){
        pkg->state.allowPathFlag = 1;
        if( ! QString::compare(item->listWidget()->objectName(), "list_page2_matchingLocations"))
        {
            ui->line_page2_location->setText(item->text().split("]").at(1));
            pkg->inP.startingPoint = item->text().split("]").at(1);
            pkg->inP.startingPointNum = guider->map->string2Num(pkg->inP.startingPoint);
            if( ! QString::compare("[沙河]", item->text().split("]")[0] + "]"))
                pkg->inP.campus = 1;
            else
                pkg->inP.campus = 0;
            ui->lbl_page2_startingPoint->setText("当前起点：" + item->text());
            addressLbl->setText("当前位置：" + pkg->inP.startingPoint);
        } else
        if( ! QString::compare(item->listWidget()->objectName(), "list_page3_matchingLocations"))
        {
            ui->line_page3_location->setText(item->text().split("]").at(1));
            pkg->inP.terminalPoint = item->text().split("]").at(1);
            pkg->inP.terminalPointNum = guider->map->string2Num(pkg->inP.terminalPoint);
            if(QString::compare(StringCampus(), item->text().split("]")[0] + "]"))
                pkg->state.corssCampusFlag = true;
            else
                pkg->state.corssCampusFlag = false;
            ui->lbl_page3_terminalPoint->setText("当前终点：" + item->text());
        } else
        if( ! QString::compare(item->listWidget()->objectName(), "list_page4_matchingLocations"))
        {
            ui->line_page4_location->setText(item->text().split("]").at(1));
        }
    });
}

/**
 * @brief 用于判断路径是否合法，合法则将合法路径Flag置为2，非法则弹窗警告
 */
void MainWindow::ConnectConfirmBtn(QPushButton *btn)
{
    connect(btn, &QPushButton::clicked, [=](){
        if( ! QString::compare(btn->objectName(), "btn_page3_confirm"))
        {
            if( ! (pkg->inP.terminalPoint.isEmpty()
             || ui->line_page3_location->text().isEmpty()
             || ui->list_page3_matchingLocations->count() == 0))
            {
                if( !QString::compare(pkg->inP.terminalPoint, ui->line_page3_location->text()))
                    pkg->state.allowPathFlag = 1;
            }
        } else
        if( ! QString::compare(btn->objectName(), "btn_page4_confirm"))
        {
            if(ui->line_page4_location->text().isEmpty())
                pkg->state.allowPathFlag = 2;
        }
        if(pkg->state.allowPathFlag == 1)
        {
            if( ! QString::compare(btn->objectName(), "btn_page2_confirm"))
            {
                if( ! QString::compare(pkg->inP.startingPoint, ui->line_page2_location->text()))
                    pkg->state.allowPathFlag = 2;
            } else
            if( ! QString::compare(btn->objectName(), "btn_page3_confirm"))
            {
                if( ! QString::compare(pkg->inP.terminalPoint, ui->line_page3_location->text()))
                {
                    if(QString::compare(pkg->inP.startingPoint, pkg->inP.terminalPoint))
                        pkg->state.allowPathFlag = 2;
                    else
                    {
                        if(pkg->state.corssCampusFlag)
                            pkg->state.allowPathFlag = 2;
                        else
                        {
                            QMessageBox::critical(this, "警告：路径非法", "起点与终点相同！");
                            goto END;
                        }
                    }
                }
            } else
            if( ! QString::compare(btn->objectName(), "btn_page4_addWaypoint"))
            {
                if( ! QString::compare(ui->list_page4_matchingLocations->currentItem()->text().split("]").at(1), ui->line_page4_location->text()))
                    pkg->state.allowPathFlag = 2;
            }
        }
        if(pkg->state.allowPathFlag != 2)
            QMessageBox::critical(this, "警告：路径非法", "请选择搜索到的路径！");
        END:;
    });
}


void MainWindow::GetSrdNum(int num)
{
    pkg->state.corssCampusFlag = false;
    guider->AddCurrentPoint(pkg);
    pkg->state.currentLocationNum = 0;
    pkg->inP.startingPointNum = 0;
    pkg->inP.terminalPoint = pkg->outP.matchingLocation.at(num);
    pkg->inP.terminalPointNum = pkg->outP.matchingLocationNum.at(num);
    pkg->outP.navigationRoute = pkg->outP.matchingRoute[num];
    pkg->outP.navigationRouteNum = pkg->outP.matchingRouteNum[num];
    pkg->outP.navigationDistance = pkg->outP.matchingSectionDistance[num];
    pkg->outP.navigationTimeSpent = pkg->outP.matchingSectionTimeSpent[num];
    pkg->inP.terminalPoint = pkg->outP.matchingRoute[num].last();
    pkg->inP.terminalPointNum = pkg->outP.matchingRouteNum[num].last();
    SetPage5();
}

/**
 * @brief 导航模块，主要用于检查跨校区的导航
 */
void MainWindow::guiderCampus()
{
    int gCdebugFlag = false;
    if(debug == false)
        gCdebugFlag = false;

    if(pkg->state.corssCampusFlag)
    {
        pkg->inP.tempTerminalPoint = pkg->inP.terminalPoint;
        if(gCdebugFlag)
            qDebug() << "guiderCampus(): pkg->myClock.time.hour()" << pkg->myClock.time.hour();
        if(pkg->myClock.time.hour() >= 8 && pkg->myClock.time.hour() <= 20)
        {
            pkg->state.busFlag = true;
            pkg->inP.terminalPoint = "校车乘车点";
        }
        else
            pkg->inP.terminalPoint = "西门";
        guider->findNavigationRoute(pkg);
        if(gCdebugFlag)
            qDebug() << "guiderCampus()" << pkg->outP.navigationRoute;
    }
    else
    {
        if( ! pkg->inP.tempTerminalPoint.isEmpty())
        {
            if(pkg->state.busFlag)
            {
                pkg->state.busFlag = false;
                pkg->inP.startingPoint = "校车乘车点";
            }
            else
                pkg->inP.startingPoint = "西门";
            pkg->inP.terminalPoint = pkg->inP.tempTerminalPoint;
        }
        guider->findNavigationRoute(pkg);
        pkg->inP.tempTerminalPoint.clear();
    }
}

/**
 * @brief 用于根据所选校区改变地图显示
 */
void MainWindow::SetPage5()
{
    pkg->myClock.speed = pkg->myClock.userSpeed;

    if(pkg->inP.campus == 0)
    {
        setGeometry(490, 30, 569, 800);
        setFixedSize(569, 800);
        ui->lbl_page5_map->setFixedSize(547, 766);
    }
    else
    {
        setGeometry(230, 30, 1095, 800);
        setFixedSize(1095, 800);
        ui->lbl_page5_map->setFixedSize(1073, 766);
    }

    PaintLable();
    pkg->state.startTime = pkg->myClock.time;
    pkg->state.navigationRuningFlag = true;
    if(pkg->state.TimeMultiplierSetFlag)
    {
        pkg->state.TimeMultiplierSetFlag = false;
        ui->spx_page5_spinBox->setValue(60);
    }
    ui->stackedWidget->setCurrentIndex(5);
}

/**
 * @brief 画出地图以及导航路线
 */
void MainWindow::PaintLable(void)
{
    int i, start, max;
    double x, y;
    bool arcPaintFlag = false;

    start = pkg->inP.campus ? 1 : guider->map->pointNumShaHe + 1;
    max = pkg->inP.campus ? guider->map->pointNumShaHe : guider->map->pointNum;
    QPen penDebug, pen;
    if(pkg->inP.campus == 0)
    {
        pix = new QPixmap(":/map/Image/Map-of-Xitucheng-Campus.png");
        painter = new QPainter(pix);
        if(debug)
        {
            penDebug.setColor(Qt::red);
            penDebug.setWidth(4);
            painter->setPen(penDebug);

            for(i = guider->map->pointNumShaHe + 1; i <= guider->map->pointNum; i++)
            {
                x = guider->map->point[i].pointX * 970. / 547 - 15;
                y = guider->map->point[i].pointY * 1359. / 766 - 14;
                painter->drawEllipse(QPointF(x, y), 3, 3);
            }
            penDebug.setColor(Qt::green);
            if(arcPaintFlag)
            {
                for(i = start; i <= max; i++)
                {
                    for(int j = start; j <= max; j++)
                    {
                        if(guider->map->arc[i][j].distance != infinite)
                        {
                            painter->drawLine(guider->map->point[i].pointX * 970. / 547 - 15,
                                              guider->map->point[i].pointY * 1359. / 766 - 14,
                                              guider->map->point[j].pointX * 970. / 547 - 15,
                                              guider->map->point[j].pointY * 1359. / 766 - 14);
                        }
                    }
                }
            }
        }

        pen.setColor(Qt::green);
        pen.setWidth(7);
        painter->setPen(pen);
        for(i = 1; (!pkg->outP.navigationRoute.isEmpty()) && i < pkg->outP.navigationRoute.size(); i++)
        {
            painter->drawLine(guider->map->point[pkg->outP.navigationRouteNum.at(i - 1)].pointX * 970. / 547 - 15,
                    guider->map->point[pkg->outP.navigationRouteNum.at(i - 1)].pointY * 1359. / 766 - 14,
                    guider->map->point[pkg->outP.navigationRouteNum.at(i)].pointX * 970. / 547 - 15,
                    guider->map->point[pkg->outP.navigationRouteNum.at(i)].pointY * 1359. / 766 - 14);
        }
    }
    else
    {
        pix = new QPixmap(":/map/Image/Map-of-Shahe-Campus.jpg");
        painter = new QPainter(pix);
        if(debug)
        {
            penDebug.setColor(Qt::red);
            penDebug.setWidth(4);
            painter->setPen(penDebug);
            for(i = 1; i <= guider->map->pointNumShaHe; i++)
            {
                x = guider->map->point[i].pointX * 2048. / 1073 - 15;
                y = guider->map->point[i].pointY * 1462. / 766 - 14;
                painter->drawEllipse(QPointF(x, y), 3, 3);
            }
            penDebug.setColor(Qt::green);
            if(arcPaintFlag)
            {
                for(i = start; i <= max; i++)
                {
                    for(int j = start; j <= max; j++)
                    {
                        if(guider->map->arc[i][j].distance != infinite)
                        {
                            painter->drawLine(guider->map->point[i].pointX * 2048. / 1073 - 15,
                                              guider->map->point[i].pointY * 1462. / 766 - 14,
                                              guider->map->point[j].pointX * 2048. / 1073 - 15,
                                              guider->map->point[j].pointY * 1462. / 766 - 14);
                        }
                    }
                }
            }
        }
        pen.setColor(Qt::green);
        pen.setWidth(7);
        painter->setPen(pen);
        for(i = 1; (!pkg->outP.navigationRoute.isEmpty()) && i < pkg->outP.navigationRoute.size(); i++)
        {
            painter->drawLine(guider->map->point[pkg->outP.navigationRouteNum.at(i - 1)].pointX * 2048. / 1073 - 15,
                    guider->map->point[pkg->outP.navigationRouteNum.at(i - 1)].pointY * 1462. / 766 - 14,
                    guider->map->point[pkg->outP.navigationRouteNum.at(i)].pointX * 2048. / 1073 - 15,
                    guider->map->point[pkg->outP.navigationRouteNum.at(i)].pointY * 1462. / 766 - 14);
        }
    }
    ui->lbl_page5_map->setPixmap(*pix);
}

/**
 * @brief 用于解决跨天时真实相差的毫秒数
 * @param startTime 起始时间
 * @param endTime 结束时间
 */
int MainWindow::TrueMsecsTo(QTime startTime, QTime endTime)
{
    int diff = startTime.msecsTo(endTime);
    return diff < 0 ? 86400000 + diff : diff;
}

/**
 * @brief 画出运动过的路线
 */
void MainWindow::Motion()
{
    int MotionRunDebugFlag = false;
    int MotionStaticDebugFlag = false;
    if( ! debug)
    {
        MotionRunDebugFlag = false;
        MotionStaticDebugFlag = false;
    }
    if(pkg->state.navigationRuningFlag)
    {
        pkg->state.terminalPointFlag = false;
        if(MotionRunDebugFlag)
        {
            qDebug() << ++pkg->state.debugNum << pkg->myClock.time << "---------------Motion() start---------------";
            qDebug() << ++pkg->state.debugNum << MotionRunDebugFlag << "currentLocationNum:" <<pkg->state.currentLocationNum;
        }
        if(pkg->state.currentLocationNum == 0)
            pkg->inP.rateOfAdvance = 2;
        else
            pkg->inP.rateOfAdvance = TrueMsecsTo(pkg->state.startTime, pkg->myClock.time) / 1000. / pkg->outP.navigationTimeSpent.at(pkg->state.currentLocationNum - 1);
        if(MotionRunDebugFlag)
                qDebug() << ++pkg->state.debugNum << ++MotionRunDebugFlag << "rateOfAdvance:" << pkg->inP.rateOfAdvance;
        if(pkg->state.corssCorrectFlag)//修正
        {
            pkg->state.corssCorrectFlag = false;
            pkg->state.startTime = pkg->myClock.time;
            pkg->inP.rateOfAdvance = 0;
            if(MotionRunDebugFlag)
                qDebug() << ++pkg->state.debugNum << ++MotionRunDebugFlag << "rateOfAdvance(修正):" << pkg->inP.rateOfAdvance;
        }
        if(pkg->inP.rateOfAdvance >= 1)
        {
            if(MotionRunDebugFlag)
            {
                qDebug() << ++pkg->state.debugNum << ++MotionRunDebugFlag << "currentLocationNum:" << pkg->state.currentLocationNum;
                qDebug() << ++pkg->state.debugNum << ++MotionRunDebugFlag << "pkg->outP.navigationRouteNum.size() - 1:" << pkg->outP.navigationRouteNum.size() - 1;
            }
            if(pkg->state.currentLocationNum == pkg->outP.navigationRouteNum.size() - 1)
            {
                if(MotionRunDebugFlag)
                    qDebug() << ++pkg->state.debugNum << ++MotionRunDebugFlag << "corssCampusFlag:" << pkg->state.corssCampusFlag;
                if(pkg->state.corssCampusFlag)
                {
                    pkg->state.navigationRuningFlag = false;
                    pkg->state.currentLocationNum = 0;
                    pkg->inP.campus = !pkg->inP.campus;
                    pkg->state.corssCampusFlag = false;
                    if(MotionStaticDebugFlag)
                        qDebug() << ++pkg->state.debugNum << "Motion() pkg->outP.navigationRoute:" << pkg->outP.navigationRoute;
                    QTime tempTime = QTime::currentTime();
                    QMessageBox::StandardButton result = QMessageBox::information(NULL, "提示", "即将开始另一校区导航");
                    if(result == QMessageBox::Ok)
                    {
                       pkg->myClock.diff += 90 * 60 * 1000;
                        guiderCampus();
                        SetPage5();
                        if(MotionRunDebugFlag)
                            qDebug() << ++pkg->state.debugNum << ++MotionRunDebugFlag << "SetPage5() end";
                        if(MotionStaticDebugFlag)
                            qDebug() << ++pkg->state.debugNum << "Motion() tempTime.msecsTo(QTime::currentTime()):" << tempTime.msecsTo(QTime::currentTime());
                        pkg->state.corssCorrectFlag = true;
                        goto InitCurrentPoint;
                    }
                }
                else
                {
                    pkg->state.navigationRuningFlag = false;
                    pkg->state.terminalPointFlag = true;
                    addressLbl->setText("当前位置：" + StringCampus() + pkg->inP.terminalPoint);
                    SendLog("到达终点：" + StringCampus() + pkg->inP.terminalPoint);
                }
            }
            else
            {
                InitCurrentPoint:
                pkg->inP.featherPointNum = pkg->outP.navigationRouteNum.at(pkg->state.currentLocationNum);
                pkg->inP.arrowPointNum = pkg->outP.navigationRouteNum.at(++pkg->state.currentLocationNum);
                QString feather, arrow;
                StringFeatherArrow(&feather, &arrow);
                SendLog("当前位置：" + StringCampus() + feather + " --> " + arrow);
                pkg->state.startTime = pkg->myClock.time.addMSecs(pkg->outP.navigationTimeSpent.at(pkg->state.currentLocationNum - 1) - TrueMsecsTo(pkg->state.startTime, pkg->myClock.time) / 1000.);
            }
        }
        pkg->inP.rateOfAdvance = TrueMsecsTo(pkg->state.startTime, pkg->myClock.time) / 1000. / pkg->outP.navigationTimeSpent.at(pkg->state.currentLocationNum - 1);
        if(MotionRunDebugFlag)
            qDebug() << ++pkg->state.debugNum << ++MotionRunDebugFlag << "rateOfAdvance:" << pkg->inP.rateOfAdvance;
        if(pkg->inP.rateOfAdvance < 0)//暂时新修正，真正的修正等待计时器的设置时间跑完后，再次调用该函数时修正
        {
            pkg->inP.rateOfAdvance = 0;
            if(MotionRunDebugFlag)
                qDebug() << ++pkg->state.debugNum << ++MotionRunDebugFlag << "rateOfAdvance(暂时修正):" << pkg->inP.rateOfAdvance;
        }
        if(pkg->inP.rateOfAdvance < 1)
        {
            pkg->inP.currentLocationX = guider->map->point[pkg->inP.featherPointNum].pointX +
                    (guider->map->point[pkg->inP.arrowPointNum].pointX - guider->map->point[pkg->inP.featherPointNum].pointX) * pkg->inP.rateOfAdvance;
            pkg->inP.currentLocationY = guider->map->point[pkg->inP.featherPointNum].pointY +
                    (guider->map->point[pkg->inP.arrowPointNum].pointY - guider->map->point[pkg->inP.featherPointNum].pointY) * pkg->inP.rateOfAdvance;
            QString feather;
            QString arrow;
            if(MotionRunDebugFlag)
            {
                qDebug() << ++pkg->state.debugNum << ++MotionRunDebugFlag << "currentLocationNum:" << pkg->state.currentLocationNum;
                qDebug() << ++pkg->state.debugNum << ++MotionRunDebugFlag << "pkg->outP.navigationRouteNum.size() - 1:" << pkg->outP.navigationRouteNum.size() - 1;
            }
            
            StringFeatherArrow(&feather, &arrow);

            if(MotionRunDebugFlag)
                qDebug() << ++pkg->state.debugNum << ++MotionRunDebugFlag << feather + " --> " + arrow;
            addressLbl->setText("当前位置：" + StringCampus()
                                + feather + " --> " + arrow
                                + "  " + QString::number((pkg->outP.navigationDistance.at(pkg->state.currentLocationNum - 1) * pkg->inP.rateOfAdvance))
                                + " / " + QString::number(pkg->outP.navigationDistance.at(pkg->state.currentLocationNum - 1))
                                + " (m)");
        }
        QPen pen(Qt::red);
        pen.setWidth(3);
        painter->setPen(pen);
        if(pkg->inP.campus)
            painter->drawEllipse(QPointF(pkg->inP.currentLocationX * 2048. / 1073 - 15, pkg->inP.currentLocationY * 1462. / 766 - 14), 3, 3);
        else
            painter->drawEllipse(QPointF(pkg->inP.currentLocationX * 970. / 547 - 15, pkg->inP.currentLocationY * 1359. / 766 - 14), 3, 3);
        ui->lbl_page5_map->setPixmap(*pix);
    }
    else
    {
        pkg->state.startTime = pkg->state.startTime.addMSecs(1000 / pkg->myClock.fps * pkg->myClock.speed);
    }
    if(MotionRunDebugFlag)
        qDebug() << ++pkg->state.debugNum << pkg->myClock.time << "---------------Motion() end---------------";
}

void MainWindow::StringFeatherArrow(QString *feather, QString *arrow)
{
    if(pkg->state.currentLocationNum == 1)
            {
                *feather = pkg->inP.startingPoint;
                *arrow = guider->map->num2String(pkg->inP.arrowPointNum);
            }
            else if(pkg->state.currentLocationNum < pkg->outP.navigationRouteNum.size() - 1)
            {
                *feather = guider->map->num2String(pkg->inP.featherPointNum);
                *arrow = guider->map->num2String(pkg->inP.arrowPointNum);
            }
            else
            {
                *feather = guider->map->num2String(pkg->inP.featherPointNum);
                *arrow = pkg->inP.terminalPoint;
            }
}

/**
 * @brief 鼠标释放事件，一般用于debug
 */
void MainWindow::mouseReleaseEvent(QMouseEvent *ev)
{
    if(debug)
    {
        bool initPointFlag = false;
        bool initArcFlag = true;
        static bool sendArcFlag = false;
        static int arc[2] = {0, 0};

        if(ev->button() == Qt::RightButton)
        {

            pkg->inP.campus = 0;
            pkg->inP.strategy = 1;
            pkg->state.corssCampusFlag = true;
            pkg->inP.startingPoint = "ATM";
            pkg->inP.terminalPoint = "ATM";
            guiderCampus();
            SetPage5();
            ui->spx_page5_spinBox->setValue(60);
            connect(ui->btn_page3_confirm,&QPushButton::clicked,[=](){
                SendLog("设置终点为：" + pkg->inP.terminalPoint);
                guiderCampus();
                SetPage5();
            });
        }
        else if(initPointFlag && ev->button() == Qt::LeftButton && ui->stackedWidget->currentIndex() == 5)
        {
            connect(this, SIGNAL(SendPoint(int, int, int)), initP, SLOT(GetPoint(int, int, int)));
            emit SendPoint(ev->position().x(), ev->position().y(), pkg->inP.campus);
            disconnect(this, SIGNAL(SendPoint(int, int, int)), initP, SLOT(GetPoint(int, int, int)));
            initP->show();
        }
        else if(initArcFlag && ev->button() == Qt::LeftButton && ui->stackedWidget->currentIndex() == 5)
        {
            connect(this, SIGNAL(SendArc(int, int, int, int, int, myGraph*)), initA, SLOT(GetArc(int, int, int, int, int, myGraph*)));
            if(sendArcFlag)
            {
                sendArcFlag = false;
                emit SendArc(arc[0], arc[1], ev->position().x(), ev->position().y(), pkg->inP.campus, guider->map);
                disconnect(this, SIGNAL(SendArc(int, int, int, int, int, myGraph*)), initA, SLOT(GetArc(int, int, int, int, int, myGraph*)));
                initA->show();
            }
            else
            {
                arc[0] = ev->position().x();
                arc[1] = ev->position().y();
                sendArcFlag = true;
                ui->statusbar->showMessage("已储存第一个点",1000);
            }
        }
    }
}

/**
 * @brief 关闭前会做的事，用于发送日志。
 */
void MainWindow::closeEvent(QCloseEvent *)
{
    SendLog("导航系统关闭,导航运行时长：" +
        QString::number(clock() / 1000 / 60) + "min " +
        QString::number((clock() / 1000.) - (clock() / 1000 / 60 * 60)) + "s");
}
